<!DOCTYPE html>
<html lang=zh>
<head>
  <meta charset="utf-8">
  
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no, minimal-ui">
  <meta name="renderer" content="webkit">
  <meta http-equiv="Cache-Control" content="no-transform" />
  <meta http-equiv="Cache-Control" content="no-siteapp" />
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="apple-mobile-web-app-status-bar-style" content="black">
  <meta name="format-detection" content="telephone=no,email=no,adress=no">
  <!-- Color theme for statusbar -->
  <meta name="theme-color" content="#000000" />
  <!-- 强制页面在当前窗口以独立页面显示,防止别人在框架里调用页面 -->
  <meta http-equiv="window-target" content="_top" />
  
  
  <title>设计模式—结构型模式 | Skyung-Blog</title>
  <meta name="description" content="设计模式—结构型模式">
<meta property="og:type" content="article">
<meta property="og:title" content="设计模式—结构型模式">
<meta property="og:url" content="https://skyung.gitee.io/Skyung/2022/03/01/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E2%80%94%E7%BB%93%E6%9E%84%E5%9E%8B%E6%A8%A1%E5%BC%8F/index.html">
<meta property="og:site_name" content="Skyung-Blog">
<meta property="og:description" content="设计模式—结构型模式">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://gitee.com/lifuh/picgo/raw/master/img/image-20211118110241740.png">
<meta property="og:image" content="https://gitee.com/lifuh/picgo/raw/master/img/1216886-20190922011430803-958922094.png">
<meta property="article:published_time" content="2022-02-28T16:00:00.000Z">
<meta property="article:modified_time" content="2022-02-28T16:00:00.000Z">
<meta property="article:author" content="Skyung">
<meta property="article:tag" content="java">
<meta property="article:tag" content="设计模式">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://gitee.com/lifuh/picgo/raw/master/img/image-20211118110241740.png">
  <!-- Canonical links -->
  <link rel="canonical" href="https://skyung.gitee.io/Skyung/2022/03/01/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E2%80%94%E7%BB%93%E6%9E%84%E5%9E%8B%E6%A8%A1%E5%BC%8F/index.html">
  
    <link rel="alternate" href="/atom.xml" title="Skyung-Blog" type="application/atom+xml">
  
  
    <link rel="icon" href="images/favicon.png" type="image/x-icon">
  
  
<link rel="stylesheet" href="/Skyung/css/style.css">

  
  
  
  
<meta name="generator" content="Hexo 5.4.1"></head>


<body class="main-center" itemscope itemtype="http://schema.org/WebPage">
  <header class="header" itemscope itemtype="http://schema.org/WPHeader">
  <div class="slimContent">
    <div class="navbar-header">
      
      
      <div class="profile-block text-center">
        <a id="avatar" href="https://github.com/cofess" target="_blank">
          <img class="img-circle img-rotate" src="/Skyung/images/avatar.jpg" width="200" height="200">
        </a>
        <h2 id="name" class="hidden-xs hidden-sm">Skyung</h2>
        <h3 id="title" class="hidden-xs hidden-sm hidden-md">Web Developer</h3>
        <small id="location" class="text-muted hidden-xs hidden-sm"><i class="icon icon-map-marker"></i> Wuhan, China</small>
      </div>
      
      <div class="search" id="search-form-wrap">

    <form class="search-form sidebar-form">
        <div class="input-group">
            <input type="text" class="search-form-input form-control" placeholder="搜索" />
            <span class="input-group-btn">
                <button type="submit" class="search-form-submit btn btn-flat" onclick="return false;"><i class="icon icon-search"></i></button>
            </span>
        </div>
    </form>
    <div class="ins-search">
  <div class="ins-search-mask"></div>
  <div class="ins-search-container">
    <div class="ins-input-wrapper">
      <input type="text" class="ins-search-input" placeholder="想要查找什么..." x-webkit-speech />
      <button type="button" class="close ins-close ins-selectable" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
    </div>
    <div class="ins-section-wrapper">
      <div class="ins-section-container"></div>
    </div>
  </div>
</div>


</div>
      <button class="navbar-toggle collapsed" type="button" data-toggle="collapse" data-target="#main-navbar" aria-controls="main-navbar" aria-expanded="false">
        <span class="sr-only">Toggle navigation</span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </button>
    </div>
    <nav id="main-navbar" class="collapse navbar-collapse" itemscope itemtype="http://schema.org/SiteNavigationElement" role="navigation">
      <ul class="nav navbar-nav main-nav ">
        
        
        <li class="menu-item menu-item-home">
          <a href="/Skyung/.">
            
            <i class="icon icon-home-fill"></i>
            
            <span class="menu-title">首页</span>
          </a>
        </li>
        
        
        <li class="menu-item menu-item-archives">
          <a href="/Skyung/archives">
            
            <i class="icon icon-archives-fill"></i>
            
            <span class="menu-title">归档</span>
          </a>
        </li>
        
        
        <li class="menu-item menu-item-categories">
          <a href="/Skyung/categories">
            
            <i class="icon icon-folder"></i>
            
            <span class="menu-title">分类</span>
          </a>
        </li>
        
        
        <li class="menu-item menu-item-tags">
          <a href="/Skyung/tags">
            
            <i class="icon icon-tags"></i>
            
            <span class="menu-title">标签</span>
          </a>
        </li>
        
        
        <li class="menu-item menu-item-repository">
          <a href="/Skyung/repository">
            
            <i class="icon icon-project"></i>
            
            <span class="menu-title">项目</span>
          </a>
        </li>
        
        
        <li class="menu-item menu-item-books">
          <a href="/Skyung/books">
            
            <i class="icon icon-book-fill"></i>
            
            <span class="menu-title">书单</span>
          </a>
        </li>
        
        
        <li class="menu-item menu-item-links">
          <a href="/Skyung/links">
            
            <i class="icon icon-friendship"></i>
            
            <span class="menu-title">友链</span>
          </a>
        </li>
        
        
        <li class="menu-item menu-item-about">
          <a href="/Skyung/about">
            
            <i class="icon icon-cup-fill"></i>
            
            <span class="menu-title">关于</span>
          </a>
        </li>
        
      </ul>
      
	
    <ul class="social-links">
    	
        <li><a href="/Skyung/null" target="_blank" title="Github" data-toggle=tooltip data-placement=top><i class="icon icon-github"></i></a></li>
        
        <li><a href="/Skyung/null" target="_blank" title="Weibo" data-toggle=tooltip data-placement=top><i class="icon icon-weibo"></i></a></li>
        
        <li><a href="/Skyung/null" target="_blank" title="Twitter" data-toggle=tooltip data-placement=top><i class="icon icon-twitter"></i></a></li>
        
        <li><a href="/Skyung/null" target="_blank" title="Behance" data-toggle=tooltip data-placement=top><i class="icon icon-behance"></i></a></li>
        
        <li><a href="/Skyung/atom.xml" target="_blank" title="Rss" data-toggle=tooltip data-placement=top><i class="icon icon-rss"></i></a></li>
        
    </ul>

    </nav>
  </div>
</header>

  
    <aside class="sidebar" itemscope itemtype="http://schema.org/WPSideBar">
  <div class="slimContent">
    
      <div class="widget">
    <h3 class="widget-title">公告</h3>
    <div class="widget-body">
        <div id="board">
            <div class="content">
                <p>欢迎交流与分享经验!</p>
            </div>
        </div>
    </div>
</div>

    
      
  <div class="widget">
    <h3 class="widget-title">分类</h3>
    <div class="widget-body">
      <ul class="category-list"><li class="category-list-item"><a class="category-list-link" href="/Skyung/categories/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/">学习笔记</a><span class="category-list-count">20</span></li></ul>
    </div>
  </div>


    
      
  <div class="widget">
    <h3 class="widget-title">标签</h3>
    <div class="widget-body">
      <ul class="tag-list" itemprop="keywords"><li class="tag-list-item"><a class="tag-list-link" href="/Skyung/tags/java/" rel="tag">java</a><span class="tag-list-count">19</span></li><li class="tag-list-item"><a class="tag-list-link" href="/Skyung/tags/jvm/" rel="tag">jvm</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/Skyung/tags/linux/" rel="tag">linux</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/Skyung/tags/redis/" rel="tag">redis</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/Skyung/tags/%E5%A4%9A%E7%BA%BF%E7%A8%8B/" rel="tag">多线程</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/Skyung/tags/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/" rel="tag">并发编程</a><span class="tag-list-count">2</span></li><li class="tag-list-item"><a class="tag-list-link" href="/Skyung/tags/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/" rel="tag">设计模式</a><span class="tag-list-count">4</span></li><li class="tag-list-item"><a class="tag-list-link" href="/Skyung/tags/%E9%9B%B6%E6%95%A3%E7%82%B9/" rel="tag">零散点</a><span class="tag-list-count">1</span></li></ul>
    </div>
  </div>


    
      
  <div class="widget">
    <h3 class="widget-title">标签云</h3>
    <div class="widget-body tagcloud">
      <a href="/Skyung/tags/java/" style="font-size: 14px;">java</a> <a href="/Skyung/tags/jvm/" style="font-size: 13px;">jvm</a> <a href="/Skyung/tags/linux/" style="font-size: 13px;">linux</a> <a href="/Skyung/tags/redis/" style="font-size: 13px;">redis</a> <a href="/Skyung/tags/%E5%A4%9A%E7%BA%BF%E7%A8%8B/" style="font-size: 13px;">多线程</a> <a href="/Skyung/tags/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/" style="font-size: 13.33px;">并发编程</a> <a href="/Skyung/tags/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/" style="font-size: 13.67px;">设计模式</a> <a href="/Skyung/tags/%E9%9B%B6%E6%95%A3%E7%82%B9/" style="font-size: 13px;">零散点</a>
    </div>
  </div>

    
      
  <div class="widget">
    <h3 class="widget-title">归档</h3>
    <div class="widget-body">
      <ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/Skyung/archives/2022/05/">五月 2022</a><span class="archive-list-count">5</span></li><li class="archive-list-item"><a class="archive-list-link" href="/Skyung/archives/2022/04/">四月 2022</a><span class="archive-list-count">7</span></li><li class="archive-list-item"><a class="archive-list-link" href="/Skyung/archives/2022/03/">三月 2022</a><span class="archive-list-count">9</span></li><li class="archive-list-item"><a class="archive-list-link" href="/Skyung/archives/2022/02/">二月 2022</a><span class="archive-list-count">1</span></li><li class="archive-list-item"><a class="archive-list-link" href="/Skyung/archives/2021/09/">九月 2021</a><span class="archive-list-count">1</span></li></ul>
    </div>
  </div>


    
      
  <div class="widget">
    <h3 class="widget-title">最新文章</h3>
    <div class="widget-body">
      <ul class="recent-post-list list-unstyled no-thumbnail">
        
          <li>
            
            <div class="item-inner">
              <p class="item-category">
                <a class="category-link" href="/Skyung/categories/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/">学习笔记</a>
              </p>
              <p class="item-title">
                <a href="/Skyung/2022/05/08/Spring/" class="title">spring</a>
              </p>
              <p class="item-date">
                <time datetime="2022-05-07T16:00:00.000Z" itemprop="datePublished">2022-05-08</time>
              </p>
            </div>
          </li>
          
          <li>
            
            <div class="item-inner">
              <p class="item-category">
                <a class="category-link" href="/Skyung/categories/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/">学习笔记</a>
              </p>
              <p class="item-title">
                <a href="/Skyung/2022/05/08/netty-RPC/" class="title">Netty-RPC</a>
              </p>
              <p class="item-date">
                <time datetime="2022-05-07T16:00:00.000Z" itemprop="datePublished">2022-05-08</time>
              </p>
            </div>
          </li>
          
          <li>
            
            <div class="item-inner">
              <p class="item-category">
                <a class="category-link" href="/Skyung/categories/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/">学习笔记</a>
              </p>
              <p class="item-title">
                <a href="/Skyung/2022/05/07/%E5%B8%B8%E7%94%A8%E7%B1%BB%E5%BA%93%E5%92%8CAPI/" class="title">常见类库</a>
              </p>
              <p class="item-date">
                <time datetime="2022-05-06T16:00:00.000Z" itemprop="datePublished">2022-05-07</time>
              </p>
            </div>
          </li>
          
          <li>
            
            <div class="item-inner">
              <p class="item-category">
                <a class="category-link" href="/Skyung/categories/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/">学习笔记</a>
              </p>
              <p class="item-title">
                <a href="/Skyung/2022/05/07/%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95/" class="title">单元测试</a>
              </p>
              <p class="item-date">
                <time datetime="2022-05-06T16:00:00.000Z" itemprop="datePublished">2022-05-07</time>
              </p>
            </div>
          </li>
          
          <li>
            
            <div class="item-inner">
              <p class="item-category">
                <a class="category-link" href="/Skyung/categories/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/">学习笔记</a>
              </p>
              <p class="item-title">
                <a href="/Skyung/2022/05/01/netty%E8%81%8A%E5%A4%A9%E5%AE%A4/" class="title">Netty聊天室</a>
              </p>
              <p class="item-date">
                <time datetime="2022-04-30T16:00:00.000Z" itemprop="datePublished">2022-05-01</time>
              </p>
            </div>
          </li>
          
      </ul>
    </div>
  </div>
  

    
  </div>
</aside>

  
  
  <aside class="sidebar sidebar-toc collapse   in  " id="collapseToc" itemscope itemtype="http://schema.org/WPSideBar">
  <div class="slimContent">
    <nav id="toc" class="article-toc">
      <h3 class="toc-title">文章目录</h3>
      <ol class="toc"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E9%80%82%E9%85%8D%E5%99%A8%E6%A8%A1%E5%BC%8F"><span class="toc-number">1.</span> <span class="toc-text">适配器模式</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E7%B1%BB%E9%80%82%E9%85%8D%E5%99%A8%E6%A8%A1%E5%BC%8F"><span class="toc-number">1.1.</span> <span class="toc-text">类适配器模式</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%AF%B9%E8%B1%A1%E9%80%82%E9%85%8D%E5%99%A8%E6%A8%A1%E5%BC%8F"><span class="toc-number">1.2.</span> <span class="toc-text">对象适配器模式</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%8E%A5%E5%8F%A3%E9%80%82%E9%85%8D%E5%99%A8%E6%A8%A1%E5%BC%8F"><span class="toc-number">1.3.</span> <span class="toc-text">接口适配器模式</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%BA%90%E7%A0%81"><span class="toc-number">1.4.</span> <span class="toc-text">源码</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%A1%A5%E6%8E%A5%E6%A8%A1%E5%BC%8F"><span class="toc-number">2.</span> <span class="toc-text">桥接模式</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E8%A3%85%E9%A5%B0%E8%80%85%E6%A8%A1%E5%BC%8F"><span class="toc-number">3.</span> <span class="toc-text">装饰者模式</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%BA%90%E7%A0%81-1"><span class="toc-number">3.1.</span> <span class="toc-text">源码</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E7%BB%84%E5%90%88%E6%A8%A1%E5%BC%8F"><span class="toc-number">4.</span> <span class="toc-text">组合模式</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%BA%90%E7%A0%81-2"><span class="toc-number">4.1.</span> <span class="toc-text">源码</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%A4%96%E8%A7%82%E6%A8%A1%E5%BC%8F"><span class="toc-number">5.</span> <span class="toc-text">外观模式</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%BA%90%E7%A0%81-3"><span class="toc-number">5.1.</span> <span class="toc-text">源码</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BA%AB%E5%85%83%E6%A8%A1%E5%BC%8F"><span class="toc-number">6.</span> <span class="toc-text">享元模式</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%BA%90%E7%A0%81-4"><span class="toc-number">6.1.</span> <span class="toc-text">源码</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BB%A3%E7%90%86%E6%A8%A1%E5%BC%8F"><span class="toc-number">7.</span> <span class="toc-text">代理模式</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E9%9D%99%E6%80%81%E4%BB%A3%E7%90%86"><span class="toc-number">7.1.</span> <span class="toc-text">静态代理</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%8A%A8%E6%80%81%E4%BB%A3%E7%90%86"><span class="toc-number">7.2.</span> <span class="toc-text">动态代理</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Cglib%E4%BB%A3%E7%90%86"><span class="toc-number">7.3.</span> <span class="toc-text">Cglib代理</span></a></li></ol></li></ol>
    </nav>
  </div>
</aside>

<main class="main" role="main">
  <div class="content">
  <article id="post-设计模式—结构型模式" class="article article-type-post" itemscope itemtype="http://schema.org/BlogPosting">
    
    <div class="article-header">
      
        
  
    <h1 class="article-title" itemprop="name">
      设计模式—结构型模式
    </h1>
  

      
      <div class="article-meta">
        <span class="article-date">
    <i class="icon icon-calendar-check"></i>
	<a href="/Skyung/2022/03/01/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E2%80%94%E7%BB%93%E6%9E%84%E5%9E%8B%E6%A8%A1%E5%BC%8F/" class="article-date">
	  <time datetime="2022-02-28T16:00:00.000Z" itemprop="datePublished">2022-03-01</time>
	</a>
</span>
        
  <span class="article-category">
    <i class="icon icon-folder"></i>
    <a class="article-category-link" href="/Skyung/categories/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/">学习笔记</a>
  </span>

        
  <span class="article-tag">
    <i class="icon icon-tags"></i>
	<a class="article-tag-link-link" href="/Skyung/tags/java/" rel="tag">java</a>, <a class="article-tag-link-link" href="/Skyung/tags/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/" rel="tag">设计模式</a>
  </span>


        

        <span class="post-comment"><i class="icon icon-comment"></i> <a href="/Skyung/2022/03/01/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E2%80%94%E7%BB%93%E6%9E%84%E5%9E%8B%E6%A8%A1%E5%BC%8F/#comments" class="article-comment-link">评论</a></span>
        
      </div>
    </div>
    <div class="article-entry marked-body" itemprop="articleBody">
      
        <p>结构型模式：把类或对象结合在一起形成一个更大的结构。适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式。</p>
<h3 id="适配器模式"><a href="#适配器模式" class="headerlink" title="适配器模式"></a>适配器模式</h3><p>适配器模式(Adapter Pattern)将某个类的接口转换成客户端期望的另一个接口表示，主的目的是兼容性，让原本因接口不匹配不能一起工作的两个类可以协同工作。其别名为包装器(Wrapper) </p>
<p>适配器模式主要分为三类：类适配器模式、对象适配器模式、接口适配器模式。</p>
<p>工作原理：</p>
<p>将一个类的接口转换成另一种接口，让原本接口不兼容的类可以兼容，从用户的角度看不到被适配者，是解耦的；用户调用适配器转化出来的目标接口方法，适配器再调用被适配者的相关接口方法。</p>
<h4 id="类适配器模式"><a href="#类适配器模式" class="headerlink" title="类适配器模式"></a>类适配器模式</h4><p>Adapter类，通过继承 src类，实现 dst 接口，完成src=&gt;dst的适配。</p>
<p>手机充电器的场景。</p>
<p>代码实现</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//被适配的类</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Voltage220V</span> &#123;</span><br><span class="line">   <span class="comment">//输出220V的电压</span></span><br><span class="line">   <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">output220V</span><span class="params">()</span> &#123;</span><br><span class="line">      <span class="type">int</span> <span class="variable">src</span> <span class="operator">=</span> <span class="number">220</span>;</span><br><span class="line">      System.out.println(<span class="string">&quot;电压=&quot;</span> + src + <span class="string">&quot;伏&quot;</span>);</span><br><span class="line">      <span class="keyword">return</span> src;</span><br><span class="line">   &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//适配接口</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">IVoltage5V</span> &#123;</span><br><span class="line">   <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">output5V</span><span class="params">()</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//适配器类</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">VoltageAdapter</span> <span class="keyword">extends</span> <span class="title class_">Voltage220V</span> <span class="keyword">implements</span> <span class="title class_">IVoltage5V</span> &#123;</span><br><span class="line">   <span class="meta">@Override</span></span><br><span class="line">   <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">output5V</span><span class="params">()</span> &#123;</span><br><span class="line">      <span class="comment">// TODO Auto-generated method stub</span></span><br><span class="line">      <span class="comment">//获取到220V电压</span></span><br><span class="line">      <span class="type">int</span> <span class="variable">srcV</span> <span class="operator">=</span> output220V();</span><br><span class="line">      <span class="type">int</span> <span class="variable">dstV</span> <span class="operator">=</span> srcV / <span class="number">44</span> ; <span class="comment">//转成 5v</span></span><br><span class="line">      <span class="keyword">return</span> dstV;</span><br><span class="line">   &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>手机调用适配接口</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Phone</span> &#123;</span><br><span class="line">   <span class="comment">//充电</span></span><br><span class="line">   <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">charging</span><span class="params">(IVoltage5V iVoltage5V)</span> &#123;</span><br><span class="line">      <span class="keyword">if</span>(iVoltage5V.output5V() == <span class="number">5</span>) &#123;</span><br><span class="line">         System.out.println(<span class="string">&quot;电压为5V, 可以充电~~&quot;</span>);</span><br><span class="line">      &#125; <span class="keyword">else</span> <span class="keyword">if</span> (iVoltage5V.output5V() &gt; <span class="number">5</span>) &#123;</span><br><span class="line">         System.out.println(<span class="string">&quot;电压大于5V, 不能充电~~&quot;</span>);</span><br><span class="line">      &#125;</span><br><span class="line">   &#125;</span><br><span class="line">   <span class="comment">//测试</span></span><br><span class="line">   <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">       <span class="type">Phone</span> <span class="variable">phone</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Phone</span>();</span><br><span class="line">       phone.charging(<span class="keyword">new</span> <span class="title class_">VoltageAdapter</span>());</span><br><span class="line">   &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><strong>类适配器模式注意事项和细节</strong> </p>
<ol>
<li>Java是单继承机制，所以类适配器需要继承src类这一点算是一个缺点, 因为这要 求dst必须是接口，有一定局限性; </li>
<li>src类的方法在Adapter中都会暴露出来，也增加了使用的成本。（VoltageAdapter类中使用了output220V()）</li>
<li> 由于其继承了src类，所以它可以根据需求重写src类的方法，使得Adapter的灵 活性增强了。</li>
</ol>
<h4 id="对象适配器模式"><a href="#对象适配器模式" class="headerlink" title="对象适配器模式"></a>对象适配器模式</h4><p>由于一般避免类的继承（合成复用原则）。</p>
<p>对象适配器模式基本思路和类的适配器模式相同，只是将Adapter类作修改，不是继承src类，而是持有src类的实例，以解决兼容性的问题。 即：持有 src类，实现 dst 接口，完成src-&gt;dst的适配。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//适配器类</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">VoltageAdapter</span> <span class="keyword">implements</span> <span class="title class_">IVoltage5V</span> &#123;</span><br><span class="line">   <span class="keyword">private</span> Voltage220V voltage220V; <span class="comment">// 关联关系-聚合</span></span><br><span class="line">   </span><br><span class="line">   <span class="comment">//通过构造器，传入一个 Voltage220V 实例</span></span><br><span class="line">   <span class="keyword">public</span> <span class="title function_">VoltageAdapter</span><span class="params">(Voltage220V voltage220v)</span> &#123; </span><br><span class="line">      <span class="built_in">this</span>.voltage220V = voltage220v;</span><br><span class="line">   &#125;</span><br><span class="line"></span><br><span class="line">   <span class="meta">@Override</span></span><br><span class="line">   <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">output5V</span><span class="params">()</span> &#123;</span><br><span class="line">      <span class="type">int</span> <span class="variable">dst</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line">      <span class="keyword">if</span>(<span class="literal">null</span> != voltage220V) &#123;</span><br><span class="line">         <span class="type">int</span> <span class="variable">src</span> <span class="operator">=</span> voltage220V.output220V();<span class="comment">//获取220V 电压</span></span><br><span class="line">         System.out.println(<span class="string">&quot;使用对象适配器，进行适配~~&quot;</span>);</span><br><span class="line">         dst = src / <span class="number">44</span>;</span><br><span class="line">         System.out.println(<span class="string">&quot;适配完成，输出的电压为=&quot;</span> + dst);</span><br><span class="line">      &#125;</span><br><span class="line">      <span class="keyword">return</span> dst;</span><br><span class="line">   &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//调用时</span></span><br><span class="line">phone.charging(<span class="keyword">new</span> <span class="title class_">VoltageAdapter</span>(<span class="keyword">new</span> <span class="title class_">Voltage220V</span>()));</span><br></pre></td></tr></table></figure>

<p>对象适配器和类适配器其实算是同一种思想，只不过实现方式不同。</p>
<h4 id="接口适配器模式"><a href="#接口适配器模式" class="headerlink" title="接口适配器模式"></a>接口适配器模式</h4><ol>
<li>一些书籍称为：适配器模式(Default Adapter Pattern)或缺省适配器模式。</li>
<li>当不需要全部实现接口提供的方法时，可先设计一个抽象类实现接口，并为该接口中每个方法提供一个默认实现（空方法），那么该抽象类的子类可有选择地覆盖父类的某些方法来实现需求</li>
<li> 适用于一个接口不想使用其所有的方法的情况。</li>
</ol>
<p>不过JDK8中接口可以有默认方法。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">Interface4</span> &#123;</span><br><span class="line">   <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">m1</span><span class="params">()</span>;</span><br><span class="line">   <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">m2</span><span class="params">()</span>;</span><br><span class="line">   <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">m3</span><span class="params">()</span>;</span><br><span class="line">   <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">m4</span><span class="params">()</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">class</span> <span class="title class_">AbsAdapter</span> <span class="keyword">implements</span> <span class="title class_">Interface4</span> &#123;</span><br><span class="line">	<span class="comment">//默认实现</span></span><br><span class="line">	<span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">m1</span><span class="params">()</span> &#123;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">m2</span><span class="params">()</span> &#123;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">m3</span><span class="params">()</span> &#123;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">m4</span><span class="params">()</span> &#123;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//调用时重写需要的方法</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;	</span><br><span class="line">    <span class="type">AbsAdapter</span> <span class="variable">absAdapter</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">AbsAdapter</span>() &#123;</span><br><span class="line">        <span class="comment">//只需要去覆盖我们需要使用 接口方法</span></span><br><span class="line">        <span class="meta">@Override</span></span><br><span class="line">        <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">m1</span><span class="params">()</span> &#123;</span><br><span class="line">            <span class="comment">// TODO Auto-generated method stub</span></span><br><span class="line">            System.out.println(<span class="string">&quot;使用了m1的方法&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;;</span><br><span class="line">    absAdapter.m1();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="源码"><a href="#源码" class="headerlink" title="源码"></a>源码</h4><ol>
<li>springMVC中请求首先发给DispatcherServlet类；</li>
<li>doDispatch()方法处理请求，通过HanderMapping的处理，找到url隐射的Hander；</li>
<li>执行Hander中的方法，也就是Controller，返回一个ModelAndView。</li>
</ol>
<p>关键在于第二步中根据不同的Hander处理不同的方法，则是采用了适配器，获取处理该Controller的适配器，通过适配器调用该Controller方法，返回ModelAndView。</p>
<p>DispatcherServlet类</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">DispatcherServlet</span> <span class="keyword">extends</span> <span class="title class_">FrameworkServlet</span> &#123;	</span><br><span class="line">    ...</span><br><span class="line">    <span class="comment">//映射url对应的Controller</span></span><br><span class="line">    <span class="keyword">private</span> List&lt;HandlerMapping&gt; handlerMappings;</span><br><span class="line">	<span class="comment">//适配器</span></span><br><span class="line">    <span class="keyword">private</span> List&lt;HandlerAdapter&gt; handlerAdapters;</span><br><span class="line">	<span class="comment">//根据request遍历controller，获取和url匹配的Controller：</span></span><br><span class="line">    <span class="keyword">protected</span> HandlerExecutionChain <span class="title function_">getHandler</span><span class="params">(HttpServletRequest request)</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">        ...</span><br><span class="line">    &#125;</span><br><span class="line">	<span class="keyword">protected</span> <span class="keyword">void</span> <span class="title function_">doDispatch</span><span class="params">(HttpServletRequest request, HttpServletResponse response)</span>&#123;</span><br><span class="line">        ...</span><br><span class="line">        <span class="comment">//讲url匹配上的controller赋值给mappedHandler</span></span><br><span class="line">        mappedHandler = <span class="built_in">this</span>.getHandler(processedRequest); </span><br><span class="line">        <span class="comment">//根据controller获取对应的适配器</span></span><br><span class="line">        <span class="type">HandlerAdapter</span> <span class="variable">ha</span> <span class="operator">=</span> <span class="built_in">this</span>.getHandlerAdapter(mappedHandler.getHandler());</span><br><span class="line">        <span class="comment">//适配器去调用controller对应的方法，返回mv</span></span><br><span class="line">        mv = ha.handle(processedRequest, response, mappedHandler.getHandler());</span><br><span class="line">    &#125;</span><br><span class="line">    ...</span><br><span class="line">    <span class="comment">//具体怎么拿到应的适配器，是通过循环遍历：</span></span><br><span class="line">    <span class="keyword">protected</span> HandlerAdapter <span class="title function_">getHandlerAdapter</span><span class="params">(Object handler)</span> <span class="keyword">throws</span> ServletException &#123;</span><br><span class="line">        <span class="keyword">if</span> (<span class="built_in">this</span>.handlerAdapters != <span class="literal">null</span>) &#123;</span><br><span class="line">            <span class="type">Iterator</span> <span class="variable">var2</span> <span class="operator">=</span> <span class="built_in">this</span>.handlerAdapters.iterator();</span><br><span class="line"></span><br><span class="line">            <span class="keyword">while</span>(var2.hasNext()) &#123;</span><br><span class="line">                <span class="type">HandlerAdapter</span> <span class="variable">adapter</span> <span class="operator">=</span> (HandlerAdapter)var2.next();</span><br><span class="line">                <span class="keyword">if</span> (adapter.supports(handler)) &#123;</span><br><span class="line">                    <span class="keyword">return</span> adapter;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">ServletException</span>(<span class="string">&quot;No adapter for handler [&quot;</span> + handler + <span class="string">&quot;]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>HandlerAdapter接口，也就是适配的接口：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">public interface HandlerAdapter &#123;</span><br><span class="line">    boolean supports(Object var1);</span><br><span class="line"></span><br><span class="line">    @Nullable</span><br><span class="line">    ModelAndView handle(HttpServletRequest var1, HttpServletResponse var2, Object var3) throws Exception;</span><br><span class="line"></span><br><span class="line">    long getLastModified(HttpServletRequest var1, Object var2);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>HandlerAdapter接口下有多个实现类，其中常用的：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">HttpRequestHandlerAdapter</span> <span class="keyword">implements</span> <span class="title class_">HandlerAdapter</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">HttpRequestHandlerAdapter</span><span class="params">()</span> &#123;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">supports</span><span class="params">(Object handler)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> handler <span class="keyword">instanceof</span> HttpRequestHandler;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Nullable</span></span><br><span class="line">    <span class="keyword">public</span> ModelAndView <span class="title function_">handle</span><span class="params">(HttpServletRequest request, HttpServletResponse response, Object handler)</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">        ((HttpRequestHandler)handler).handleRequest(request, response);</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="type">long</span> <span class="title function_">getLastModified</span><span class="params">(HttpServletRequest request, Object handler)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> handler <span class="keyword">instanceof</span> LastModified ? ((LastModified)handler).getLastModified(request) : -<span class="number">1L</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><strong>思考：</strong></p>
<p>为什么要使用适配器模式呢？</p>
<p>Controller可以理解为Adapter（被适配者）其中之一，可以看到处理器（宽泛的概念Controller，以及HttpRequestHandler，Servlet，等等）的类型不同，有多重实现方式，那么调用方式就不是确定的，如果需要直接调用Controller方法，需要调用的时候就得不断是使用if else来进行判断是哪一种子类然后执行。那么如果后面要扩展（宽泛的概念Controller，以及HttpRequestHandler，Servlet，等等）Controller，就得修改原来的代码，这样违背了开闭原则（对修改关闭，对扩展开放）。</p>
<p>Spring创建了一个适配器接口（HandlerAdapter）使得每一种处理器（宽泛的概念Controller，以及HttpRequestHandler，Servlet，等等）有一种对应的适配器实现类，让适配器代替（宽泛的概念Controller，以及HttpRequestHandler，Servlet，等等）执行相应的方法。这样在扩展Controller 时，只需要增加一个适配器类就完成了SpringMVC的扩展了。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">HandlerAdapter</span> &#123;</span><br><span class="line">	<span class="type">boolean</span> <span class="title function_">supports</span><span class="params">(Object handler)</span>;</span><br><span class="line">	ModelAndView <span class="title function_">handle</span><span class="params">(HttpServletRequest request, HttpServletResponse response, Object handler)</span> <span class="keyword">throws</span> Exception;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>supports()方法传入处理器（宽泛的概念Controller，以及HttpRequestHandler，Servlet，等等）判断是否与当前适配器支持如果支持则从DispatcherServlet中的HandlerAdapter实现类中返回支持的适配器实现类。handler方法就是代理Controller来执行请求的方法并返回结果。</p>
<p><strong>手写SpringMVC通过适配器设计模式获取到对应的Controller的源码</strong></p>
<p>被适配的类</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//多种Controller实现  </span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">Controller</span> &#123;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">HttpController</span> <span class="keyword">implements</span> <span class="title class_">Controller</span> &#123;</span><br><span class="line">   <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">doHttpHandler</span><span class="params">()</span> &#123;</span><br><span class="line">      System.out.println(<span class="string">&quot;http...&quot;</span>);</span><br><span class="line">   &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">SimpleController</span> <span class="keyword">implements</span> <span class="title class_">Controller</span> &#123;</span><br><span class="line">   <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">doSimplerHandler</span><span class="params">()</span> &#123;</span><br><span class="line">      System.out.println(<span class="string">&quot;simple...&quot;</span>);</span><br><span class="line">   &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">AnnotationController</span> <span class="keyword">implements</span> <span class="title class_">Controller</span> &#123;</span><br><span class="line">   <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">doAnnotationHandler</span><span class="params">()</span> &#123;</span><br><span class="line">      System.out.println(<span class="string">&quot;annotation...&quot;</span>);</span><br><span class="line">   &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>适配器：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">///定义一个Adapter接口，可以看作适配的接口</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">HandlerAdapter</span> &#123;</span><br><span class="line">   <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">supports</span><span class="params">(Object handler)</span>;</span><br><span class="line"></span><br><span class="line">   <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">handle</span><span class="params">(Object handler)</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 多种适配器类</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">SimpleHandlerAdapter</span> <span class="keyword">implements</span> <span class="title class_">HandlerAdapter</span> &#123;</span><br><span class="line"></span><br><span class="line">   <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">handle</span><span class="params">(Object handler)</span> &#123;</span><br><span class="line">      ((SimpleController) handler).doSimplerHandler();</span><br><span class="line">   &#125;</span><br><span class="line"></span><br><span class="line">   <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">supports</span><span class="params">(Object handler)</span> &#123;</span><br><span class="line">      <span class="keyword">return</span> (handler <span class="keyword">instanceof</span> SimpleController);</span><br><span class="line">   &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">HttpHandlerAdapter</span> <span class="keyword">implements</span> <span class="title class_">HandlerAdapter</span> &#123;</span><br><span class="line"></span><br><span class="line">   <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">handle</span><span class="params">(Object handler)</span> &#123;</span><br><span class="line">      ((HttpController) handler).doHttpHandler();</span><br><span class="line">   &#125;</span><br><span class="line"></span><br><span class="line">   <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">supports</span><span class="params">(Object handler)</span> &#123;</span><br><span class="line">      <span class="keyword">return</span> (handler <span class="keyword">instanceof</span> HttpController);</span><br><span class="line">   &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">AnnotationHandlerAdapter</span> <span class="keyword">implements</span> <span class="title class_">HandlerAdapter</span> &#123;</span><br><span class="line"></span><br><span class="line">   <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">handle</span><span class="params">(Object handler)</span> &#123;</span><br><span class="line">      ((AnnotationController) handler).doAnnotationHandler();</span><br><span class="line">   &#125;</span><br><span class="line"></span><br><span class="line">   <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">supports</span><span class="params">(Object handler)</span> &#123;</span><br><span class="line"></span><br><span class="line">      <span class="keyword">return</span> (handler <span class="keyword">instanceof</span> AnnotationController);</span><br><span class="line">   &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>DispatchServlet类：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">DispatchServlet</span> &#123;</span><br><span class="line"></span><br><span class="line">   <span class="keyword">public</span> <span class="keyword">static</span> List&lt;HandlerAdapter&gt; handlerAdapters = <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;HandlerAdapter&gt;();</span><br><span class="line"></span><br><span class="line">   <span class="keyword">public</span> <span class="title function_">DispatchServlet</span><span class="params">()</span> &#123;</span><br><span class="line">      handlerAdapters.add(<span class="keyword">new</span> <span class="title class_">AnnotationHandlerAdapter</span>());</span><br><span class="line">      handlerAdapters.add(<span class="keyword">new</span> <span class="title class_">HttpHandlerAdapter</span>());</span><br><span class="line">      handlerAdapters.add(<span class="keyword">new</span> <span class="title class_">SimpleHandlerAdapter</span>());</span><br><span class="line">   &#125;</span><br><span class="line"></span><br><span class="line">   <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">doDispatch</span><span class="params">()</span> &#123;</span><br><span class="line"></span><br><span class="line">      <span class="comment">// 此处模拟SpringMVC从request取handler的对象，</span></span><br><span class="line">      <span class="comment">// 假设取到的是HttpController</span></span><br><span class="line">       <span class="type">HttpController</span> <span class="variable">controller</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">HttpController</span>();</span><br><span class="line">      <span class="comment">// AnnotationController controller = new AnnotationController();</span></span><br><span class="line">      <span class="comment">//SimpleController controller = new SimpleController();</span></span><br><span class="line">      <span class="comment">// 得到对应适配器</span></span><br><span class="line">      <span class="type">HandlerAdapter</span> <span class="variable">adapter</span> <span class="operator">=</span> getHandler(controller);</span><br><span class="line">      <span class="comment">// 通过适配器执行对应的controller对应方法</span></span><br><span class="line">      adapter.handle(controller);</span><br><span class="line"></span><br><span class="line">   &#125;</span><br><span class="line"></span><br><span class="line">   <span class="keyword">public</span> HandlerAdapter <span class="title function_">getHandler</span><span class="params">(Controller controller)</span> &#123;</span><br><span class="line">      <span class="comment">//遍历：根据得到的controller(handler), 返回对应适配器</span></span><br><span class="line">      <span class="keyword">for</span> (HandlerAdapter adapter : <span class="built_in">this</span>.handlerAdapters) &#123;</span><br><span class="line">         <span class="keyword">if</span> (adapter.supports(controller)) &#123;</span><br><span class="line">            <span class="keyword">return</span> adapter;</span><br><span class="line">         &#125;</span><br><span class="line">      &#125;</span><br><span class="line">      <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line">   &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><strong>关键是通过适配器的handle()方法调用对应的被适配的controller的方法。</strong></p>
<h3 id="桥接模式"><a href="#桥接模式" class="headerlink" title="桥接模式"></a>桥接模式</h3><p>实际场景：图形有不同的形状和颜色，传统的方式需要为每个形状的颜色单独建类。</p>
<p>存在的问题：扩展性问题，如果再增加图形的形状或者颜色，就需要排列组合增加多个类。</p>
<p>桥接模式(Bridge模式)是指：将<strong>实现与抽象放在两个不同的类层次中</strong>，使两个层次可以独立改变。 Bridge模式基于类的最小设计原则，通过使用封装、聚合及继承等行为让不同的类承担不同的职责。它的主要特点是把抽象(Abstraction)与行为实现 (Implementation)分离开来，从而可以保持各部分的独立性以及应对他们的功能扩展。</p>
<p>对于上面的图形来说，就是把形状和颜色两个维度分开。</p>
<p>案例代码实现：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//颜色接口</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">Color</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">bepaint</span><span class="params">(String shape)</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//白色</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">White</span> <span class="keyword">implements</span> <span class="title class_">Color</span>&#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">bepaint</span><span class="params">(String shape)</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;白色的&quot;</span> + shape);</span><br><span class="line">    &#125;</span><br><span class="line"> </span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//黑色</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Black</span> <span class="keyword">implements</span> <span class="title class_">Color</span>&#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">bepaint</span><span class="params">(String shape)</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;黑色的&quot;</span> + shape);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>将另一个维度形状和颜色组合在一起。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">class</span> <span class="title class_">Shape</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> Color color;</span><br><span class="line"> </span><br><span class="line">	<span class="keyword">public</span> <span class="title function_">Shape</span><span class="params">(Color color)</span> &#123;</span><br><span class="line">		<span class="built_in">super</span>();</span><br><span class="line">		<span class="built_in">this</span>.color = color;</span><br><span class="line">	&#125;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">void</span> <span class="title function_">draw</span><span class="params">()</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>抽象类的扩展：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Circle</span> <span class="keyword">extends</span> <span class="title class_">Shape</span>&#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">draw</span><span class="params">()</span> &#123;</span><br><span class="line">        color.bepaint(<span class="string">&quot;正方形&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Square</span> <span class="keyword">extends</span> <span class="title class_">Shape</span>&#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">draw</span><span class="params">()</span> &#123;</span><br><span class="line">        color.bepaint(<span class="string">&quot;正方形&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>调用时：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">Shape</span> <span class="variable">square</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Square</span>(<span class="keyword">new</span> <span class="title class_">White</span>());</span><br></pre></td></tr></table></figure>

<p>桥接模式替代多层继承方案，可以减少子类的个数，降低系统的管理和维护成本。</p>
<p>桥接模式要求正确识别出系统中两个独立变化的维度，因此其使用范围有一定的局限性，即需要有这样的应用场景。</p>
<p>可使用的场景：JDBC驱动程序；银行转账系统 转账分类: 网上转账，柜台转账，AMT转账 转账用户类型：普通用户，银卡用户，金卡用户..；消息管理，消息类型：即时消息，延时消息 消息分类：手机短信，邮件消息，QQ消息。</p>
<h3 id="装饰者模式"><a href="#装饰者模式" class="headerlink" title="装饰者模式"></a>装饰者模式</h3><p>星巴克咖啡订单项目（咖啡馆）：</p>
<p>咖啡种类：Espresso(意大利浓咖啡)、ShortBlack、LongBlack(美式 咖啡)、Decaf(无因咖啡)；</p>
<p>调料：Milk、Soy(豆浆)、Chocolate；</p>
<p>需要计算不同种类咖啡的费用: 客户可以点单品咖啡，也可以单品咖 啡+调料组合。</p>
<p>传统的方案：</p>
<p><img src="https://gitee.com/lifuh/picgo/raw/master/img/image-20211118110241740.png" alt="image-20211118110241740"></p>
<p>问题：会有很多类，当我们增加一个单品咖啡，或者一个新的调料， 类的数量就会倍增，就会出现类爆炸。</p>
<p>装饰者模式：动态的将新功能附加到对象上。在对象功能扩展方面，它比继承更有弹性，装饰者模式也体现了开闭原则。</p>
<p>装饰者模式的类图：</p>
<p><img src="https://gitee.com/lifuh/picgo/raw/master/img/1216886-20190922011430803-958922094.png" alt="img"></p>
<p>以饮料为主体，然后在运行时以调料来“装饰”（decorate）饮料。比方说，如果顾客想要摩卡和奶泡深焙咖啡，那么，要做的是：拿一个深焙咖啡（DarkRoast）对象，以摩卡（Mocha）对象装饰它，以奶泡（Whip）对象装饰它，调用cost()方法，并依赖委托（delegate）将调料的价钱加上去。</p>
<p>代码实现：</p>
<p>饮料</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//饮料抽象类：</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">class</span> <span class="title class_">Drink</span> &#123;</span><br><span class="line"></span><br><span class="line">	<span class="keyword">public</span> String des; <span class="comment">// 描述</span></span><br><span class="line">	<span class="keyword">private</span> <span class="type">float</span> <span class="variable">price</span> <span class="operator">=</span> <span class="number">0.0f</span>;</span><br><span class="line">	<span class="keyword">public</span> String <span class="title function_">getDes</span><span class="params">()</span> &#123;</span><br><span class="line">		<span class="keyword">return</span> des;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setDes</span><span class="params">(String des)</span> &#123;</span><br><span class="line">		<span class="built_in">this</span>.des = des;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="keyword">public</span> <span class="type">float</span> <span class="title function_">getPrice</span><span class="params">()</span> &#123;</span><br><span class="line">		<span class="keyword">return</span> price;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setPrice</span><span class="params">(<span class="type">float</span> price)</span> &#123;</span><br><span class="line">		<span class="built_in">this</span>.price = price;</span><br><span class="line">	&#125;</span><br><span class="line">	</span><br><span class="line">	<span class="comment">//计算费用的抽象方法子类来实现</span></span><br><span class="line">	<span class="keyword">public</span> <span class="keyword">abstract</span> <span class="type">float</span> <span class="title function_">cost</span><span class="params">()</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>被装饰者：单一的咖啡</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//咖啡抽象类</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Coffee</span>  <span class="keyword">extends</span> <span class="title class_">Drink</span> &#123;</span><br><span class="line">   <span class="meta">@Override</span></span><br><span class="line">   <span class="keyword">public</span> <span class="type">float</span> <span class="title function_">cost</span><span class="params">()</span> &#123;</span><br><span class="line">      <span class="comment">// TODO Auto-generated method stub</span></span><br><span class="line">      <span class="keyword">return</span> <span class="built_in">super</span>.getPrice();</span><br><span class="line">   &#125;  </span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//一种咖啡</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">LongBlack</span> <span class="keyword">extends</span> <span class="title class_">Coffee</span> &#123;</span><br><span class="line">	<span class="keyword">public</span> <span class="title function_">LongBlack</span><span class="params">()</span> &#123;</span><br><span class="line">		setDes(<span class="string">&quot; longblack &quot;</span>);</span><br><span class="line">		setPrice(<span class="number">5.0f</span>);</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//一种咖啡</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ShortBlack</span> <span class="keyword">extends</span> <span class="title class_">Coffee</span>&#123;</span><br><span class="line">	<span class="keyword">public</span> <span class="title function_">ShortBlack</span><span class="params">()</span> &#123;</span><br><span class="line">		setDes(<span class="string">&quot; shortblack &quot;</span>);</span><br><span class="line">		setPrice(<span class="number">4.0f</span>);</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>装饰者：调料</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//调料装饰者抽象类（继承自饮料抽象类）</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Decorator</span> <span class="keyword">extends</span> <span class="title class_">Drink</span> &#123;</span><br><span class="line">	<span class="keyword">private</span> Drink obj;</span><br><span class="line">	</span><br><span class="line">	<span class="keyword">public</span> <span class="title function_">Decorator</span><span class="params">(Drink obj)</span> &#123; <span class="comment">//组合</span></span><br><span class="line">		<span class="built_in">this</span>.obj = obj;</span><br><span class="line">	&#125;</span><br><span class="line">	</span><br><span class="line">	<span class="meta">@Override</span></span><br><span class="line">	<span class="keyword">public</span> <span class="type">float</span> <span class="title function_">cost</span><span class="params">()</span> &#123;</span><br><span class="line">		<span class="comment">// getPrice 自己价格</span></span><br><span class="line">		<span class="keyword">return</span> <span class="built_in">super</span>.getPrice() + obj.cost();</span><br><span class="line">	&#125;</span><br><span class="line">	</span><br><span class="line">	<span class="meta">@Override</span></span><br><span class="line">	<span class="keyword">public</span> String <span class="title function_">getDes</span><span class="params">()</span> &#123;</span><br><span class="line">		<span class="comment">// obj.getDes() 输出被装饰者的信息</span></span><br><span class="line">		<span class="keyword">return</span> des + <span class="string">&quot; &quot;</span> + getPrice() + <span class="string">&quot; &amp;&amp; &quot;</span> + obj.getDes();</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//一种调料</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Milk</span> <span class="keyword">extends</span> <span class="title class_">Decorator</span> &#123;</span><br><span class="line">    </span><br><span class="line">	<span class="keyword">public</span> <span class="title function_">Milk</span><span class="params">(Drink obj)</span> &#123;</span><br><span class="line">		<span class="built_in">super</span>(obj);</span><br><span class="line">		setDes(<span class="string">&quot; 牛奶 &quot;</span>);</span><br><span class="line">		setPrice(<span class="number">2.0f</span>); </span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Chocolate</span> <span class="keyword">extends</span> <span class="title class_">Decorator</span> &#123;</span><br><span class="line"></span><br><span class="line">	<span class="keyword">public</span> <span class="title function_">Chocolate</span><span class="params">(Drink obj)</span> &#123;</span><br><span class="line">		<span class="built_in">super</span>(obj);</span><br><span class="line">		setDes(<span class="string">&quot; 巧克力 &quot;</span>);</span><br><span class="line">		setPrice(<span class="number">3.0f</span>); <span class="comment">// 调味品 的价格</span></span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>调用：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">CoffeeBar</span> &#123;</span><br><span class="line">   <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">      <span class="comment">// 装饰者模式下的订单：2份巧克力+一份牛奶的LongBlack</span></span><br><span class="line">      <span class="comment">// 1. 点一份 LongBlack</span></span><br><span class="line">      <span class="type">Drink</span> <span class="variable">order</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">LongBlack</span>();</span><br><span class="line">      <span class="comment">// 2. order 加入一份牛奶</span></span><br><span class="line">      order = <span class="keyword">new</span> <span class="title class_">Milk</span>(order);</span><br><span class="line">      <span class="comment">// 3. order 加入一份巧克力</span></span><br><span class="line">      order = <span class="keyword">new</span> <span class="title class_">Chocolate</span>(order);</span><br><span class="line">      <span class="comment">// 4. order 加入一份巧克力</span></span><br><span class="line">      order = <span class="keyword">new</span> <span class="title class_">Chocolate</span>(order);</span><br><span class="line">      System.out.println(<span class="string">&quot;order 加入一份牛奶 加入2份巧克力   费用 =&quot;</span> + order.cost());</span><br><span class="line">      System.out.println(<span class="string">&quot;order 加入一份牛奶 加入2份巧克力 描述 = &quot;</span> + order.getDes());  </span><br><span class="line">   &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><strong>关键在于每个装饰者有个属性，用来保存被装饰的对象，同时咖啡和调料继承于饮料（即Component），所以被装饰后还是drink，可以层层装饰，递归的方式套娃。</strong></p>
<h4 id="源码-1"><a href="#源码-1" class="headerlink" title="源码"></a>源码</h4><p>Java的IO结构，FilterInputStream就是一个装饰者。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//是一个抽象类，即Component；</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">class</span> <span class="title class_">InputStream</span> <span class="keyword">implements</span> <span class="title class_">Closeable</span>&#123;&#125;</span><br><span class="line"><span class="comment">//是一个装饰者类Decorator；</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">FilterInputStream</span> <span class="keyword">extends</span> <span class="title class_">InputStream</span> &#123;</span><br><span class="line">    <span class="comment">//被装饰的对象</span></span><br><span class="line">	<span class="keyword">protected</span> <span class="keyword">volatile</span> InputStream in;</span><br><span class="line">    <span class="keyword">protected</span> <span class="title function_">FilterInputStream</span><span class="params">(InputStream in)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.in = in;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//DataInputStream等就是FilterInputStream的子类</span></span><br></pre></td></tr></table></figure>

<h3 id="组合模式"><a href="#组合模式" class="headerlink" title="组合模式"></a>组合模式</h3><p>组合模式（Composite Pattern），又叫部分整体模式，它创建了对象组的树形结构，将对象组合成树状结构以表示“整体-部分”的层次关系。组合模式使得用户对单个对象和组合对象的访问具有一致性，即：<strong>组合能让客户以一致的方式处理个别对象以及组合对象（不必区分是节点还是叶子）</strong>。</p>
<p>分为三部分：</p>
<ol>
<li><p>Component：组合对象的申明接口，在适当情况下，实现所有类共有的接口默认行为,用于访问和管理Component 子 部件, Component 可以是抽象类或者接口。</p>
</li>
<li><p>Leaf：组合中的叶子节点，叶子节点没有子节点。</p>
</li>
<li><p>Composite：非叶子节点，用于存储子部件，在Component中实现子部件的相关操作。</p>
</li>
</ol>
<p>学校、学院、系的案例的代码实现：</p>
<p>Component：<strong>采用默认实现而不是抽象是因为有些方法叶子节点不需要实现。</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">class</span> <span class="title class_">OrganizationComponent</span> &#123;</span><br><span class="line"></span><br><span class="line">   <span class="keyword">private</span> String name; <span class="comment">// 名字</span></span><br><span class="line">   <span class="keyword">private</span> String des; <span class="comment">// 说明</span></span><br><span class="line">   </span><br><span class="line">   <span class="keyword">protected</span>  <span class="keyword">void</span> <span class="title function_">add</span><span class="params">(OrganizationComponent organizationComponent)</span> &#123;</span><br><span class="line">      <span class="comment">//默认实现</span></span><br><span class="line">      <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">UnsupportedOperationException</span>();</span><br><span class="line">   &#125;</span><br><span class="line">   <span class="keyword">protected</span>  <span class="keyword">void</span> <span class="title function_">remove</span><span class="params">(OrganizationComponent organizationComponent)</span> &#123;</span><br><span class="line">      <span class="comment">//默认实现</span></span><br><span class="line">      <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">UnsupportedOperationException</span>();</span><br><span class="line">   &#125;</span><br><span class="line"></span><br><span class="line">   <span class="comment">//构造器</span></span><br><span class="line">   <span class="keyword">public</span> <span class="title function_">OrganizationComponent</span><span class="params">(String name, String des)</span> &#123;</span><br><span class="line">      <span class="built_in">super</span>();</span><br><span class="line">      <span class="built_in">this</span>.name = name;</span><br><span class="line">      <span class="built_in">this</span>.des = des;</span><br><span class="line">   &#125;</span><br><span class="line"></span><br><span class="line">   <span class="keyword">public</span> String <span class="title function_">getName</span><span class="params">()</span> &#123;</span><br><span class="line">      <span class="keyword">return</span> name;</span><br><span class="line">   &#125;</span><br><span class="line">   <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setName</span><span class="params">(String name)</span> &#123;</span><br><span class="line">      <span class="built_in">this</span>.name = name;</span><br><span class="line">   &#125;</span><br><span class="line">   <span class="keyword">public</span> String <span class="title function_">getDes</span><span class="params">()</span> &#123;</span><br><span class="line">      <span class="keyword">return</span> des;</span><br><span class="line">   &#125;</span><br><span class="line">   <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setDes</span><span class="params">(String des)</span> &#123;</span><br><span class="line">      <span class="built_in">this</span>.des = des;</span><br><span class="line">   &#125;</span><br><span class="line">   <span class="comment">//方法print, 做成抽象的, 子类都需要实现</span></span><br><span class="line">   <span class="keyword">protected</span> <span class="keyword">abstract</span> <span class="keyword">void</span> <span class="title function_">print</span><span class="params">()</span>;  </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>Composite：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//University 就是 Composite , 可以管理College</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">University</span> <span class="keyword">extends</span> <span class="title class_">OrganizationComponent</span> &#123;</span><br><span class="line"></span><br><span class="line">   List&lt;OrganizationComponent&gt; organizationComponents = <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;OrganizationComponent&gt;();</span><br><span class="line"></span><br><span class="line">   <span class="comment">// 构造器</span></span><br><span class="line">   <span class="keyword">public</span> <span class="title function_">University</span><span class="params">(String name, String des)</span> &#123;</span><br><span class="line">      <span class="built_in">super</span>(name, des);</span><br><span class="line">   &#125;</span><br><span class="line"></span><br><span class="line">   <span class="comment">// 重写add</span></span><br><span class="line">   <span class="meta">@Override</span></span><br><span class="line">   <span class="keyword">protected</span> <span class="keyword">void</span> <span class="title function_">add</span><span class="params">(OrganizationComponent organizationComponent)</span> &#123;</span><br><span class="line">      organizationComponents.add(organizationComponent);</span><br><span class="line">   &#125;</span><br><span class="line"></span><br><span class="line">   <span class="comment">// 重写remove</span></span><br><span class="line">   <span class="meta">@Override</span></span><br><span class="line">   <span class="keyword">protected</span> <span class="keyword">void</span> <span class="title function_">remove</span><span class="params">(OrganizationComponent organizationComponent)</span> &#123;</span><br><span class="line">      organizationComponents.remove(organizationComponent);</span><br><span class="line">   &#125;</span><br><span class="line"></span><br><span class="line">   <span class="comment">// print方法，就是输出University 包含的学院</span></span><br><span class="line">   <span class="meta">@Override</span></span><br><span class="line">   <span class="keyword">protected</span> <span class="keyword">void</span> <span class="title function_">print</span><span class="params">()</span> &#123;</span><br><span class="line">      System.out.println(<span class="string">&quot;--------------&quot;</span> + getName() + <span class="string">&quot;--------------&quot;</span>);</span><br><span class="line">      <span class="keyword">for</span> (OrganizationComponent organizationComponent : organizationComponents) &#123;</span><br><span class="line">         organizationComponent.print();</span><br><span class="line">      &#125;</span><br><span class="line">   &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//学院</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">College</span> <span class="keyword">extends</span> <span class="title class_">OrganizationComponent</span> &#123;</span><br><span class="line">	List&lt;OrganizationComponent&gt; organizationComponents = <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;OrganizationComponent&gt;();</span><br><span class="line"></span><br><span class="line">	<span class="keyword">public</span> <span class="title function_">College</span><span class="params">(String name, String des)</span> &#123;</span><br><span class="line">		<span class="built_in">super</span>(name, des);</span><br><span class="line">		<span class="comment">// TODO Auto-generated constructor stub</span></span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	<span class="meta">@Override</span></span><br><span class="line">	<span class="keyword">protected</span> <span class="keyword">void</span> <span class="title function_">add</span><span class="params">(OrganizationComponent organizationComponent)</span> &#123;</span><br><span class="line">		<span class="comment">// 将来实际业务中，Colleage 的 add 和  University add 不一定完全一样</span></span><br><span class="line">		organizationComponents.add(organizationComponent);</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	<span class="meta">@Override</span></span><br><span class="line">	<span class="keyword">protected</span> <span class="keyword">void</span> <span class="title function_">remove</span><span class="params">(OrganizationComponent organizationComponent)</span> &#123;</span><br><span class="line">		organizationComponents.remove(organizationComponent);</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	<span class="comment">// print方法，就是输出University 包含的学院</span></span><br><span class="line">	<span class="meta">@Override</span></span><br><span class="line">	<span class="keyword">protected</span> <span class="keyword">void</span> <span class="title function_">print</span><span class="params">()</span> &#123;</span><br><span class="line">		System.out.println(<span class="string">&quot;--------------&quot;</span> + getName() + <span class="string">&quot;--------------&quot;</span>);</span><br><span class="line">		<span class="keyword">for</span> (OrganizationComponent organizationComponent : organizationComponents) &#123;</span><br><span class="line">			organizationComponent.print();</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>Leaf:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Department</span> <span class="keyword">extends</span> <span class="title class_">OrganizationComponent</span> &#123;</span><br><span class="line"></span><br><span class="line">   <span class="comment">//没有集合</span></span><br><span class="line">   <span class="keyword">public</span> <span class="title function_">Department</span><span class="params">(String name, String des)</span> &#123;</span><br><span class="line">      <span class="built_in">super</span>(name, des);</span><br><span class="line">   &#125;</span><br><span class="line">   <span class="comment">//add , remove 就不用写了，因为他是叶子节点</span></span><br><span class="line">   <span class="meta">@Override</span></span><br><span class="line">   <span class="keyword">protected</span> <span class="keyword">void</span> <span class="title function_">print</span><span class="params">()</span> &#123;</span><br><span class="line">      System.out.println(getName());</span><br><span class="line">   &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="源码-2"><a href="#源码-2" class="headerlink" title="源码"></a>源码</h4><p>HashMap可以看作运用了源码模式。map里面可以放map，层层套娃。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//相当于Component，put方法只做了默认的实现</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">class</span> <span class="title class_">AbstractMap</span>&lt;K,V&gt; <span class="keyword">implements</span> <span class="title class_">Map</span>&lt;K,V&gt; &#123;</span><br><span class="line">    <span class="keyword">public</span> V <span class="title function_">put</span><span class="params">(K key, V value)</span> &#123;</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">UnsupportedOperationException</span>();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//相当于Composite：</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">HashMap</span>&lt;K,V&gt; <span class="keyword">extends</span> <span class="title class_">AbstractMap</span>&lt;K,V&gt;</span><br><span class="line">    <span class="keyword">implements</span> <span class="title class_">Map</span>&lt;K,V&gt;, Cloneable, Serializable &#123;&#125;</span><br><span class="line"><span class="comment">//Node可以视为最终的叶子节点</span></span><br></pre></td></tr></table></figure>

<p>组合模式的总结：</p>
<ul>
<li>简化客户端操作。客户端只需要面对一致的对象而不用考虑整体部分或者节点叶子的问题。</li>
<li>具有较强的扩展性。当要更改组合对象时，只需要调整内部的层次关系， 客户端不用做出任何改动.。</li>
<li>需要遍历组织机构，或者处理的对象具有树形结构时, 非常适合使用组合模式。</li>
<li>要求较高的抽象性，如果节点和叶子有很多差异性的话，比如很多方法和属性 都不一样，不适合使用组合模式。</li>
</ul>
<h3 id="外观模式"><a href="#外观模式" class="headerlink" title="外观模式"></a>外观模式</h3><p>比如有一个需求：</p>
<p>组建一个家庭影院： DVD播放器、投影仪、自动屏幕、环绕立体声、爆米花机,要求完成使用家庭影院的 功能，其过程为： 直接用遥控器：统筹各设备开关，开爆米花机，放下屏幕，开投影仪，开音响，开DVD，选dvd，去拿爆米花，调暗灯光，播放，观影结束后，关闭各种设备。</p>
<p>传统的方式实现需要在客户端中，创建各个子系统的对象，并直接去调用子系统(对象) 相关方法，会造成调用过程混乱，没有清晰的过程。</p>
<p>解决思路：定义一个高层接口，给子系统中的一组接口提供一个一致的界面(比如在高层接口提供四个方法 ready, play, pause, end )，用来访问子系统中的 一群接口。</p>
<p>外观模式（Facade），也叫“过程模式：外观模式为子系统中的一组接口提供 一个一致的界面，此模式定义了一个高层接口，用以屏蔽内部子系统的细节，使得调用端只需跟高层发生调用，而无需关心这个子系统的内部细节。也就是套娃…</p>
<p>代码实现：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//外观类，过程类</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">HomeTheaterFacade</span> &#123;</span><br><span class="line">   <span class="comment">//定义各个子系统对象</span></span><br><span class="line">   <span class="keyword">private</span> TheaterLight theaterLight;</span><br><span class="line">   <span class="keyword">private</span> Screen screen;</span><br><span class="line">   <span class="keyword">private</span> DVDPlayer dVDPlayer;</span><br><span class="line">   </span><br><span class="line">   </span><br><span class="line">   <span class="comment">//构造器</span></span><br><span class="line">   <span class="keyword">public</span> <span class="title function_">HomeTheaterFacade</span><span class="params">()</span> &#123;</span><br><span class="line">      <span class="built_in">super</span>();</span><br><span class="line">      <span class="built_in">this</span>.theaterLight = TheaterLight.getInstance();</span><br><span class="line">      <span class="built_in">this</span>.screen = Screen.getInstance();</span><br><span class="line">      <span class="built_in">this</span>.dVDPlayer = DVDPlayer.getInstanc();</span><br><span class="line">   &#125;</span><br><span class="line"></span><br><span class="line">   <span class="comment">//操作分成 4 步</span></span><br><span class="line">   </span><br><span class="line">   <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">ready</span><span class="params">()</span> &#123;</span><br><span class="line">      screen.down();</span><br><span class="line">      dVDPlayer.on();</span><br><span class="line">      theaterLight.dim();</span><br><span class="line">   &#125;</span><br><span class="line">   </span><br><span class="line">   <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">play</span><span class="params">()</span> &#123;</span><br><span class="line">      dVDPlayer.play();</span><br><span class="line">   &#125;</span><br><span class="line">   </span><br><span class="line">   <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">pause</span><span class="params">()</span> &#123;</span><br><span class="line">      dVDPlayer.pause();</span><br><span class="line">   &#125;</span><br><span class="line">   </span><br><span class="line">   <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">end</span><span class="params">()</span> &#123;</span><br><span class="line">      theaterLight.bright();</span><br><span class="line">      screen.up();</span><br><span class="line">      dVDPlayer.off();</span><br><span class="line">   &#125; </span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//子系统</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">DVDPlayer</span> &#123;</span><br><span class="line">	<span class="comment">//使用单例模式, 使用饿汉式</span></span><br><span class="line">	<span class="keyword">private</span> <span class="keyword">static</span> <span class="type">DVDPlayer</span> <span class="variable">instance</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">DVDPlayer</span>();</span><br><span class="line">	<span class="keyword">public</span> <span class="keyword">static</span> DVDPlayer <span class="title function_">getInstanc</span><span class="params">()</span> &#123;</span><br><span class="line">		<span class="keyword">return</span> instance;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">on</span><span class="params">()</span> &#123;</span><br><span class="line">		System.out.println(<span class="string">&quot; dvd on &quot;</span>);</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">off</span><span class="params">()</span> &#123;</span><br><span class="line">		System.out.println(<span class="string">&quot; dvd off &quot;</span>);</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">play</span><span class="params">()</span> &#123;</span><br><span class="line">		System.out.println(<span class="string">&quot; dvd is playing &quot;</span>);</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">pause</span><span class="params">()</span> &#123;</span><br><span class="line">		System.out.println(<span class="string">&quot; dvd pause ..&quot;</span>);</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//...</span></span><br><span class="line"><span class="comment">//调用</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Client</span> &#123;</span><br><span class="line">	<span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">		<span class="type">HomeTheaterFacade</span> <span class="variable">homeTheaterFacade</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">HomeTheaterFacade</span>();</span><br><span class="line">		homeTheaterFacade.ready();</span><br><span class="line">		homeTheaterFacade.play();</span><br><span class="line">		homeTheaterFacade.end();</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="源码-3"><a href="#源码-3" class="headerlink" title="源码"></a>源码</h4><p>MyBatis 中的Configuration 去创建MetaObject 对象使用到外观模式。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//外观类</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Configuration</span> &#123;</span><br><span class="line">    <span class="comment">//子系统</span></span><br><span class="line">	<span class="keyword">protected</span> <span class="type">ReflectorFactory</span> <span class="variable">reflectorFactory</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">DefaultReflectorFactory</span>();</span><br><span class="line">	<span class="keyword">protected</span> <span class="type">ObjectFactory</span> <span class="variable">objectFactory</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">DefaultObjectFactory</span>();</span><br><span class="line">	<span class="keyword">protected</span> <span class="type">ObjectWrapperFactory</span> <span class="variable">objectWrapperFactory</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">DefaultObjectWrapperFactory</span>();</span><br><span class="line">	<span class="keyword">public</span> MetaObject <span class="title function_">newMetaObject</span><span class="params">(Object object)</span> &#123;</span><br><span class="line">		<span class="keyword">return</span> MetaObject.forObject(object, objectFactory, objectWrapperFactory,reflectorFactory);</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>注意：不能过多的或者不合理的使用外观模式，<strong>使用外观模式好，还是直接调用模块好， 要以让系统有层次，利于维护为目的</strong>。</p>
<h3 id="享元模式"><a href="#享元模式" class="headerlink" title="享元模式"></a>享元模式</h3><p>享元模式（Flyweight Pattern） 也叫蝇量模式: 运用共享技术有效地支持大量细粒度的对象。</p>
<p>享元模式能够解决<strong>重复对象的内存浪费的问题</strong>， 当系统中有大量相似对象，需要缓冲池时。不需总是创建新象，可以从缓冲池里拿。这样可以降低系统内存，同时提高效率。</p>
<p>享元模式常用于系统底层开发，解决系统的性能问题。经典的应用场景就是池技术了，String常量池、数据库连接池、缓冲池等等都是享元模式的应用，里面都是创建好的对象，有需要的则直接拿来用，避免重新创建，如果没有需要的，则创建一个。</p>
<p>模式的角色：</p>
<ol>
<li>FlyWeight 是抽象的享元角色, 他是产品的抽象类，同时定义出对象的外部状态和内部状态的接口或实现。</li>
<li> ConcreteFlyWeight是具体的享元角色，是具体的产品类，实现抽象角色定义相关业务。</li>
<li>UnSharedConcreteFlyWeight是不可共享的角色，也就是不可以共享的外部状态，它以参数的形式注入具体享元的相关方法中。</li>
<li>FlyWeightFactory享元工厂类，用于构建一个池容器，同时提供从池中获取对象的方法。</li>
</ol>
<p>对象的信息分为两个部分：内部状态和外部状态。内部状态指对象共享出来的信息，存储在享元对象内部且不会随环境的改变而改变。外部状态指对象得以依赖的一个标记，是随环境改变而改变的、不可共享的状态。比如棋子的颜色就是内部状态，棋子的位置就是外部状态。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//抽象享元角色</span></span><br><span class="line"><span class="keyword">interface</span> <span class="title class_">Flyweight</span>&#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">operation</span><span class="params">(UnsharedConcreteFlyweight state)</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//具体享元角色</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">ConcreteFlyweight</span> <span class="keyword">implements</span> <span class="title class_">Flyweight</span>&#123;</span><br><span class="line">    <span class="keyword">private</span> String key;</span><br><span class="line">    ConcreteFlyweight(String key)&#123;</span><br><span class="line">        <span class="built_in">this</span>.key=key;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">operation</span><span class="params">(UnsharedConcreteFlyweight outState)</span>&#123;</span><br><span class="line">        System.out.print(<span class="string">&quot;具体享元&quot;</span>+key+<span class="string">&quot;被调用，&quot;</span>);</span><br><span class="line">        System.out.println(<span class="string">&quot;非享元信息是:&quot;</span>+outState.getInfo());</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//非享元角色</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">UnsharedConcreteFlyweight</span>&#123;</span><br><span class="line">    <span class="keyword">private</span> String info;</span><br><span class="line">    UnsharedConcreteFlyweight(String info)&#123;</span><br><span class="line">        <span class="built_in">this</span>.info=info;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">getInfo</span><span class="params">()</span>&#123;</span><br><span class="line">        <span class="keyword">return</span> info;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setInfo</span><span class="params">(String info)</span>&#123;</span><br><span class="line">        <span class="built_in">this</span>.info=info;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//享元工厂角色</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">FlyweightFactory</span>&#123;</span><br><span class="line">    <span class="keyword">private</span> HashMap&lt;String, Flyweight&gt; flyweights=<span class="keyword">new</span> <span class="title class_">HashMap</span>&lt;String, Flyweight&gt;();</span><br><span class="line">    <span class="keyword">public</span> Flyweight <span class="title function_">getFlyweight</span><span class="params">(String key)</span>&#123;</span><br><span class="line">        Flyweight flyweight=(Flyweight)flyweights.get(key);</span><br><span class="line">        <span class="keyword">if</span>(flyweight!=<span class="literal">null</span>)&#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;具体享元&quot;</span>+key+<span class="string">&quot;已经存在，被成功获取！&quot;</span>);</span><br><span class="line">        &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">            flyweight=<span class="keyword">new</span> <span class="title class_">ConcreteFlyweight</span>(key);</span><br><span class="line">            flyweights.put(key, flyweight);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> flyweight;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//调用</span></span><br><span class="line">FlyweightFactory factory=<span class="keyword">new</span> <span class="title class_">FlyweightFactory</span>();</span><br><span class="line">Flyweight f01=factory.getFlyweight(<span class="string">&quot;a&quot;</span>);</span><br><span class="line">f01.operation(<span class="keyword">new</span> <span class="title class_">UnsharedConcreteFlyweight</span>(<span class="string">&quot;第1次调用a&quot;</span>));</span><br></pre></td></tr></table></figure>

<p><strong>核心就是将内部状态和外部状态分开</strong></p>
<h4 id="源码-4"><a href="#源码-4" class="headerlink" title="源码"></a>源码</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//x==y是true</span></span><br><span class="line"><span class="type">Integer</span> <span class="variable">x</span> <span class="operator">=</span> Integer.valueOf(<span class="number">127</span>);</span><br><span class="line"><span class="type">Integer</span> <span class="variable">y</span> <span class="operator">=</span> Integer.valueOf(<span class="number">127</span>);</span><br></pre></td></tr></table></figure>

<p>Integer源码中</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//池子</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">class</span> <span class="title class_">IntegerCache</span> &#123;</span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">int</span> <span class="variable">low</span> <span class="operator">=</span> -<span class="number">128</span>;</span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">int</span> high;</span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">final</span> Integer cache[];</span><br><span class="line">    cache = <span class="keyword">new</span> <span class="title class_">Integer</span>[(high - low) + <span class="number">1</span>];</span><br><span class="line">    <span class="type">int</span> <span class="variable">j</span> <span class="operator">=</span> low;</span><br><span class="line">    <span class="keyword">for</span>(<span class="type">int</span> <span class="variable">k</span> <span class="operator">=</span> <span class="number">0</span>; k &lt; cache.length; k++)</span><br><span class="line">        cache[k] = <span class="keyword">new</span> <span class="title class_">Integer</span>(j++);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> Integer <span class="title function_">valueOf</span><span class="params">(<span class="type">int</span> i)</span> &#123;</span><br><span class="line">    <span class="keyword">if</span> (i &gt;= IntegerCache.low &amp;&amp; i &lt;= IntegerCache.high)</span><br><span class="line">        <span class="keyword">return</span> IntegerCache.cache[i + (-IntegerCache.low)];</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Integer</span>(i);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>x在-128到127之间时，是采用享元模式创建对象，不需要重新new。</p>
<p>小结：“享”就表示共享，“元”表示对象。享元模式提高了系统的复杂度。需要分离出内部状态和外部状态，而外部状态具有 固化特性，不应该随着内部状态的改变而改变，这是使用享元模式需要注意的地方。</p>
<h3 id="代理模式"><a href="#代理模式" class="headerlink" title="代理模式"></a>代理模式</h3><p>代理模式：为一个对象提供一个替身，以控制对这个对象的访问。即通过代理对象访问目标对象。这样做的好处是可以在目标对象实现的基础上，增强额外的功能操作，即扩展目标对象的功能。</p>
<p>被代理的对象可以是<strong>远程对象、创建开销大的对象或需要安全控制的对象</strong>。</p>
<p>代理模式有不同的形式, 主要有三种：静态代理、动态代理 (JDK代理、接口代理)和 Cglib代理 (可以在内存动态的创建对象，而不需要实现接口， 他是属于 动态代理的范畴) 。</p>
<h4 id="静态代理"><a href="#静态代理" class="headerlink" title="静态代理"></a>静态代理</h4><p>静态代理在使用时，需要定义接口或者父类。被代理对象(即目标对象)与代理对象一 起实现相同的接口或者是继承相同父类。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//接口</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">ITeacherDao</span> &#123;</span><br><span class="line">   <span class="keyword">void</span> <span class="title function_">teach</span><span class="params">()</span>; <span class="comment">// 授课的方法</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//被代理类</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">TeacherDao</span> <span class="keyword">implements</span> <span class="title class_">ITeacherDao</span> &#123;</span><br><span class="line">	<span class="meta">@Override</span></span><br><span class="line">	<span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">teach</span><span class="params">()</span> &#123;</span><br><span class="line">		<span class="comment">// TODO Auto-generated method stub</span></span><br><span class="line">		System.out.println(<span class="string">&quot; 老师授课中  。。。。。&quot;</span>);</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//代理对象,静态代理</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">TeacherDaoProxy</span> <span class="keyword">implements</span> <span class="title class_">ITeacherDao</span>&#123;</span><br><span class="line">	<span class="keyword">private</span> ITeacherDao target; <span class="comment">// 目标对象，通过接口来聚合</span></span><br><span class="line">	<span class="comment">//构造器</span></span><br><span class="line">	<span class="keyword">public</span> <span class="title function_">TeacherDaoProxy</span><span class="params">(ITeacherDao target)</span> &#123;</span><br><span class="line">		<span class="built_in">this</span>.target = target;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="meta">@Override</span></span><br><span class="line">	<span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">teach</span><span class="params">()</span> &#123;</span><br><span class="line">		<span class="comment">// TODO Auto-generated method stub</span></span><br><span class="line">		System.out.println(<span class="string">&quot;开始代理  完成某些操作。。。。。 &quot;</span>);</span><br><span class="line">		target.teach();</span><br><span class="line">		System.out.println(<span class="string">&quot;提交。。。。。&quot;</span>);</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//调用</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Client</span> &#123;</span><br><span class="line">	<span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">		<span class="comment">//创建目标对象(被代理对象)</span></span><br><span class="line">		<span class="type">TeacherDao</span> <span class="variable">teacherDao</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">TeacherDao</span>();</span><br><span class="line">		<span class="comment">//创建代理对象, 同时将被代理对象传递给代理对象</span></span><br><span class="line">		<span class="type">TeacherDaoProxy</span> <span class="variable">teacherDaoProxy</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">TeacherDaoProxy</span>(teacherDao);</span><br><span class="line">		<span class="comment">//通过代理对象，调用到被代理对象的方法</span></span><br><span class="line">		teacherDaoProxy.teach();</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>静态代理的缺点：代理对象需要与目标对象实现一样的接口，所以会有很多代理类。一旦接口增加方法，目标对象与代理对象都要维护。</p>
<h4 id="动态代理"><a href="#动态代理" class="headerlink" title="动态代理"></a>动态代理</h4><p>代理对象不需要实现接口，但是目标对象要实现接口，否则不能用动态代理；代理对象的生成，是利用JDK的API，动态的在内存中构建代理对象。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//接口和被代理对象同上</span></span><br><span class="line"><span class="comment">//代理工厂</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ProxyFactory</span> &#123;</span><br><span class="line">	<span class="comment">//给目标对象 生成一个代理对象（可以通过构造器传，也可以静态方法直接传）</span></span><br><span class="line">	<span class="keyword">public</span> <span class="keyword">static</span> Object <span class="title function_">getProxyInstance</span><span class="params">(Object obj)</span> &#123;</span><br><span class="line">		<span class="keyword">return</span> Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), <span class="keyword">new</span> <span class="title class_">InvocationHandler</span>() &#123;</span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="keyword">public</span> Object <span class="title function_">invoke</span><span class="params">(Object proxy, Method method, Object[] args)</span> <span class="keyword">throws</span> Throwable &#123;</span><br><span class="line">                System.out.println(<span class="string">&quot;JDK代理开始~~&quot;</span>);<span class="comment">//调用invoke方法之前执行</span></span><br><span class="line">                <span class="comment">//反射机制调用目标对象的方法</span></span><br><span class="line">                <span class="type">Object</span> <span class="variable">returnVal</span> <span class="operator">=</span> method.invoke(obj, args);</span><br><span class="line">                System.out.println(<span class="string">&quot;JDK代理提交&quot;</span>);<span class="comment">//调用invoke方法之前执行</span></span><br><span class="line">                <span class="keyword">return</span> returnVal;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;); </span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//写法二，当InvocationHandler中的逻辑比较复杂时</span></span><br><span class="line"><span class="comment">//编写一个调用逻辑处理器Handler类，提供日志增强功能，并实现InvocationHandler接口</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyInvocationHandler</span> <span class="keyword">implements</span> <span class="title class_">InvocationHandler</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> Object obj;  <span class="comment">// 被代理的对象，实际的方法执行者</span></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">InvocationHandler</span><span class="params">(Object obj)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.obj = obj;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> Object <span class="title function_">invoke</span><span class="params">(Object proxy, Method method, Object[] args)</span> <span class="keyword">throws</span> Throwable &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;JDK代理开始~~&quot;</span>);<span class="comment">//调用invoke方法之前执行</span></span><br><span class="line">        <span class="comment">//反射机制调用目标对象的方法</span></span><br><span class="line">        <span class="type">Object</span> <span class="variable">returnVal</span> <span class="operator">=</span> method.invoke(obj, args);</span><br><span class="line">        System.out.println(<span class="string">&quot;JDK代理提交&quot;</span>);<span class="comment">//调用invoke方法之前执行</span></span><br><span class="line">        <span class="keyword">return</span> returnVal;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//调用</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Client</span> &#123;</span><br><span class="line">	<span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">		<span class="comment">//创建目标对象</span></span><br><span class="line">		<span class="type">ITeacherDao</span> <span class="variable">target</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">TeacherDao</span>();</span><br><span class="line">		<span class="comment">//给目标对象，创建代理对象, 可以转成 ITeacherDao</span></span><br><span class="line">		<span class="type">ITeacherDao</span> <span class="variable">proxyInstance</span> <span class="operator">=</span> (ITeacherDao)<span class="keyword">new</span> <span class="title class_">ProxyFactory</span>(target).getProxyInstance();</span><br><span class="line">        <span class="comment">//写法二</span></span><br><span class="line">        <span class="type">InvocationHandler</span> <span class="variable">Handler</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">MyInvocationHandler</span>(target);</span><br><span class="line">        <span class="type">ITeacherDao</span> <span class="variable">proxyInstance</span> <span class="operator">=</span> (ITeacherDao)Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces()，);</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>Proxy.newProxyInstance()方法中关键的三个参数：</p>
<ol>
<li><p>ClassLoader loader ： 指定当前目标对象使用的类加载器, 获取加载器的方法固定；</p>
</li>
<li><p>Class&lt;?&gt;[] interfaces: 目标对象实现的接口类型，使用泛型方法确认类型；</p>
</li>
<li><p> InvocationHandler h : 事情处理，执行目标对象的方法时，会触发事情处理器方法, 会把当前执行的目标对象方法作为参数传入。</p>
</li>
</ol>
<h4 id="Cglib代理"><a href="#Cglib代理" class="headerlink" title="Cglib代理"></a>Cglib代理</h4><p>静态代理和JDK代理模式都要求目标对象是实现一个接口，但是有时候目标对象只是一个单独的对象，并没有实现任何的接口，这个时候可使用目标对象子类来实现代理，这就是Cglib代理。</p>
<p>Cglib代理也叫作子类代理，它是在内存中构建一个子类对象从而实现对目标对象功能扩展，也将Cglib代理归属到动态代理。</p>
<p>Cglib包的底层是通过使用字节码处理框架ASM来转换字节码并生成新的类。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">TeacherDao</span> &#123;</span><br><span class="line">   <span class="keyword">public</span> String <span class="title function_">teach</span><span class="params">()</span> &#123;</span><br><span class="line">      System.out.println(<span class="string">&quot; 老师授课中，我是cglib代理，不需要实现接口&quot;</span>);</span><br><span class="line">      <span class="keyword">return</span> <span class="string">&quot;hello&quot;</span>;</span><br><span class="line">   &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ProxyFactory</span> <span class="keyword">implements</span> <span class="title class_">MethodInterceptor</span> &#123;</span><br><span class="line">	<span class="comment">//维护一个目标对象</span></span><br><span class="line">	<span class="keyword">private</span> Object target;</span><br><span class="line">	</span><br><span class="line">	<span class="comment">//构造器，传入一个被代理的对象</span></span><br><span class="line">	<span class="keyword">public</span> <span class="title function_">ProxyFactory</span><span class="params">(Object target)</span> &#123;</span><br><span class="line">		<span class="built_in">this</span>.target = target;</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	<span class="comment">//返回target对象的代理对象</span></span><br><span class="line">	<span class="keyword">public</span> Object <span class="title function_">getProxyInstance</span><span class="params">()</span> &#123;</span><br><span class="line">		<span class="comment">//1. 创建一个工具类</span></span><br><span class="line">		<span class="type">Enhancer</span> <span class="variable">enhancer</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Enhancer</span>();</span><br><span class="line">		<span class="comment">//2. 设置父类</span></span><br><span class="line">		enhancer.setSuperclass(target.getClass());</span><br><span class="line">		<span class="comment">//3. 设置回调函数</span></span><br><span class="line">		enhancer.setCallback(<span class="built_in">this</span>);</span><br><span class="line">		<span class="comment">//4. 创建子类对象，即代理对象</span></span><br><span class="line">		<span class="keyword">return</span> enhancer.create();</span><br><span class="line">	&#125;</span><br><span class="line">	</span><br><span class="line">	<span class="comment">//重写  intercept 方法，会调用目标对象的方法</span></span><br><span class="line">	<span class="meta">@Override</span></span><br><span class="line">	<span class="keyword">public</span> Object <span class="title function_">intercept</span><span class="params">(Object arg0, Method method, Object[] args, MethodProxy arg3)</span> <span class="keyword">throws</span> Throwable &#123;</span><br><span class="line">		System.out.println(<span class="string">&quot;Cglib代理模式 ~~ 开始&quot;</span>);</span><br><span class="line">		<span class="type">Object</span> <span class="variable">returnVal</span> <span class="operator">=</span> method.invoke(target, args);</span><br><span class="line">		System.out.println(<span class="string">&quot;Cglib代理模式 ~~ 提交&quot;</span>);</span><br><span class="line">		<span class="keyword">return</span> returnVal;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><strong>几种常见的代理模式</strong></p>
<ol>
<li>防火墙代理。内网通过代理穿透防火墙，实现对公网的访问。</li>
<li> 缓存代理。比如：当请求图片文件等资源时，先到缓存代理取，如果取到资源则ok，如果取不到资源， 再到公网或者数据库取，然后缓存。</li>
<li>远程代理。远程对象的本地代表，通过它可以把远程对象当本地对象来调用。远程代理通过网络和真正的远程对象沟通信息。</li>
<li>同步代理：主要使用在多线程编程中，完成多线程间同步工作。</li>
</ol>

      
    </div>
    <div class="article-footer">
      <blockquote class="mt-2x">
  <ul class="post-copyright list-unstyled">
    
    <li class="post-copyright-link hidden-xs">
      <strong>本文链接：</strong>
      <a href="https://skyung.gitee.io/Skyung/2022/03/01/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E2%80%94%E7%BB%93%E6%9E%84%E5%9E%8B%E6%A8%A1%E5%BC%8F/" title="设计模式—结构型模式" target="_blank" rel="external">https://skyung.gitee.io/Skyung/2022/03/01/设计模式—结构型模式/</a>
    </li>
    
    <li class="post-copyright-license">
      <strong>版权声明： </strong> 本博客所有文章除特别声明外，均采用 <a href="http://creativecommons.org/licenses/by/4.0/deed.zh" target="_blank" rel="external">CC BY 4.0 CN协议</a> 许可协议。转载请注明出处！
    </li>
  </ul>
</blockquote>


<div class="panel panel-default panel-badger">
  <div class="panel-body">
    <figure class="media">
      <div class="media-left">
        <a href="https://github.com/cofess" target="_blank" class="img-burn thumb-sm visible-lg">
          <img src="/Skyung/images/avatar.jpg" class="img-rounded w-full" alt="">
        </a>
      </div>
      <div class="media-body">
        <h3 class="media-heading"><a href="https://github.com/cofess" target="_blank"><span class="text-dark">Skyung</span><small class="ml-1x">Web Developer</small></a></h3>
        <div>脚踏实地，仰望星空</div>
      </div>
    </figure>
  </div>
</div>


    </div>
  </article>
  
    
  <section id="comments">
  	
      <div id="uyan_frame"></div>
    
  </section>


  
</div>

  <nav class="bar bar-footer clearfix" data-stick-bottom>
  <div class="bar-inner">
  
  <ul class="pager pull-left">
    
    <li class="prev">
      <a href="/Skyung/2022/03/01/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E2%80%94%E8%AE%BE%E8%AE%A1%E5%8E%9F%E5%88%99/" title="设计模式—设计原则"><i class="icon icon-angle-left" aria-hidden="true"></i><span>&nbsp;&nbsp;上一篇</span></a>
    </li>
    
    
    <li class="next">
      <a href="/Skyung/2022/03/01/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E2%80%94%E8%A1%8C%E4%B8%BA%E5%9E%8B%E6%A8%A1%E5%BC%8F/" title="设计模式—行为型模式"><span>下一篇&nbsp;&nbsp;</span><i class="icon icon-angle-right" aria-hidden="true"></i></a>
    </li>
    
    
    <li class="toggle-toc">
      <a class="toggle-btn " data-toggle="collapse" href="#collapseToc" aria-expanded="false" title="文章目录" role="button">    <span>[&nbsp;</span><span>文章目录</span>
        <i class="text-collapsed icon icon-anchor"></i>
        <i class="text-in icon icon-close"></i>
        <span>]</span>
      </a>
    </li>
    
  </ul>
  
  
  <!-- Button trigger modal -->
  <button type="button" class="btn btn-fancy btn-donate pop-onhover bg-gradient-warning" data-toggle="modal" data-target="#donateModal"><span>赏</span></button>
  <!-- <div class="wave-icon wave-icon-danger btn-donate" data-toggle="modal" data-target="#donateModal">
    <div class="wave-circle"><span class="icon"><i class="icon icon-bill"></i></span></div>
  </div> -->
  
  
  <div class="bar-right">
    
    <div class="share-component" data-sites="weibo,qq,wechat,facebook,twitter" data-mobile-sites="weibo,qq,qzone"></div>
    
  </div>
  </div>
</nav>
  
<!-- Modal -->
<div class="modal modal-center modal-small modal-xs-full fade" id="donateModal" tabindex="-1" role="dialog">
  <div class="modal-dialog" role="document">
    <div class="modal-content donate">
      <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
      <div class="modal-body">
        <div class="donate-box">
          <div class="donate-head">
            <p>感谢您的支持，我会继续努力的!</p>
          </div>
          <div class="tab-content">
            <div role="tabpanel" class="tab-pane fade active in" id="alipay">
              <div class="donate-payimg">
                <img src="/Skyung/images/donate/alipay.jpg" alt="扫码支持" title="扫一扫" />
              </div>
              <p class="text-muted mv">扫码打赏，你说多少就多少</p>
              <p class="text-grey">打开支付宝扫一扫，即可进行扫码打赏哦</p>
            </div>
            <div role="tabpanel" class="tab-pane fade" id="wechatpay">
              <div class="donate-payimg">
                <img src="/Skyung/images/donate/wechat.jpg" alt="扫码支持" title="扫一扫" />
              </div>
              <p class="text-muted mv">扫码打赏，你说多少就多少</p>
              <p class="text-grey">打开微信扫一扫，即可进行扫码打赏哦</p>
            </div>
          </div>
          <div class="donate-footer">
            <ul class="nav nav-tabs nav-justified" role="tablist">
              <li role="presentation" class="active">
                <a href="#alipay" id="alipay-tab" role="tab" data-toggle="tab" aria-controls="alipay" aria-expanded="true"><i class="icon icon-alipay"></i> 支付宝</a>
              </li>
              <li role="presentation" class="">
                <a href="#wechatpay" role="tab" id="wechatpay-tab" data-toggle="tab" aria-controls="wechatpay" aria-expanded="false"><i class="icon icon-wepay"></i> 微信支付</a>
              </li>
            </ul>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>



</main>

  <footer class="footer" itemscope itemtype="http://schema.org/WPFooter">
	
	
    <ul class="social-links">
    	
        <li><a href="/Skyung/null" target="_blank" title="Github" data-toggle=tooltip data-placement=top><i class="icon icon-github"></i></a></li>
        
        <li><a href="/Skyung/null" target="_blank" title="Weibo" data-toggle=tooltip data-placement=top><i class="icon icon-weibo"></i></a></li>
        
        <li><a href="/Skyung/null" target="_blank" title="Twitter" data-toggle=tooltip data-placement=top><i class="icon icon-twitter"></i></a></li>
        
        <li><a href="/Skyung/null" target="_blank" title="Behance" data-toggle=tooltip data-placement=top><i class="icon icon-behance"></i></a></li>
        
        <li><a href="/Skyung/atom.xml" target="_blank" title="Rss" data-toggle=tooltip data-placement=top><i class="icon icon-rss"></i></a></li>
        
    </ul>

    <div class="copyright">
    	
        <div class="publishby">
        	Theme by <a href="https://github.com/cofess" target="_blank"> cofess </a>base on <a href="https://github.com/cofess/hexo-theme-pure" target="_blank">pure</a>.
        </div>
    </div>
</footer>
  <script src="//cdn.jsdelivr.net/npm/jquery@1.12.4/dist/jquery.min.js"></script>
<script>
window.jQuery || document.write('<script src="js/jquery.min.js"><\/script>')
</script>

<script src="/Skyung/js/plugin.min.js"></script>


<script src="/Skyung/js/application.js"></script>


    <script>
(function (window) {
    var INSIGHT_CONFIG = {
        TRANSLATION: {
            POSTS: '文章',
            PAGES: '页面',
            CATEGORIES: '分类',
            TAGS: '标签',
            UNTITLED: '(未命名)',
        },
        ROOT_URL: '/Skyung/',
        CONTENT_URL: '/Skyung/content.json',
    };
    window.INSIGHT_CONFIG = INSIGHT_CONFIG;
})(window);
</script>

<script src="/Skyung/js/insight.js"></script>






   




   
    
    <script defer type="text/javascript" src="http://v2.uyan.cc/code/uyan.js?uid=[object Object]"></script>








</body>
</html>